package com.w08e.waai.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.w08e.waai.dto.TradingStrategyResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * AI交易策略服务
 * @Author: 智能交易策略系统
 * @Date: 2025/1/14
 */
@Service
@Slf4j
public class AiStrategyService {
    
    @Value("${ai.api.base-url}")
    private String aiApiBaseUrl;
    
    @Value("${ai.api.key}")
    private String aiApiKey;
    
    @Value("${ai.api.model}")
    private String aiModel;
    
    @Value("${ai.api.timeout:30}")
    private Integer timeout;
    
    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    
    public AiStrategyService() {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
    }
    
    /**
     * 调用AI生成交易策略
     */
    public TradingStrategyResponse generateTradingStrategy(String symbol, String klineData) {
        log.info("开始生成 {} 的AI交易策略", symbol);
        
        try {
            String prompt = buildProfessionalTraderPrompt(symbol, klineData);
            String aiResponse = callAiApi(prompt);
            
            TradingStrategyResponse strategy = parseAiResponse(symbol, aiResponse);
            strategy.setGeneratedAt(LocalDateTime.now());
            strategy.setSymbol(symbol);
            strategy.setRawAiResponse(aiResponse);
            
            log.info("成功生成 {} 的AI交易策略", symbol);
            return strategy;
            
        } catch (Exception e) {
            log.error("生成AI交易策略失败: {}", e.getMessage(), e);
            return createErrorStrategy(symbol, e.getMessage());
        }
    }
    
    /**
     * 构建专业交易员Prompt
     */
    private String buildProfessionalTraderPrompt(String symbol, String klineData) {
        return String.format("""
            你是一名胜率超过85%%的专业数字货币量化交易员，拥有超过10年的交易经验。
            请基于我提供的 %s 合约多时间框架K线数据进行专业分析。
            
            【提供的数据说明】
            - 5分钟数据：最近24小时超短线数据（288个数据点）- 用于精确入场点分析
            - 15分钟数据：最近24小时短线数据（96个数据点）- 用于短线趋势确认
            - 30分钟数据：最近48小时短中线数据（96个数据点）- 用于短期策略制定
            - 1小时数据：最近72小时中短线数据（72个数据点）- 用于趋势分析
            - 4小时数据：最近30天中期数据（180个数据点）- 用于中期趋势分析
            - 日线数据：最近90天长期数据（90个数据点）- 用于长期趋势和关键位分析
            
            【数据分析要求】
            1. 综合分析多时间框架（5分钟、15分钟、30分钟、1小时、4小时、日线）的技术指标和趋势
            2. 识别关键支撑位、阻力位和价格通道
            3. 分析成交量变化、异常成交量和市场情绪
            4. 评估当前市场趋势强度、动能和转折点
            5. 识别图表模式（双顶、头肩、三角形等）
            6. 分析移动平均线排列和背离情况
            
            【策略输出格式】请严格按照以下格式输出：
            
            === 短期策略（15分钟-4小时） ===
            方向：[LONG/SHORT/HOLD]
            进场价：[具体价格，基于5-15分钟精确分析]
            止盈价：[具体价格]
            止损价：[具体价格]
            理由：[基于短周期技术指标、支撑阻力位分析，不超过120字]
            
            === 长期策略（1-7天） ===
            方向：[LONG/SHORT/HOLD]
            进场价：[具体价格，基于4小时-日线分析]
            止盈价：[具体价格]
            止损价：[具体价格]
            理由：[基于中长周期趋势、关键技术位、市场结构分析，不超过150字]
            
            === 仓位管理 ===
            仓位比例：[具体百分比，如25%%]
            杠杆倍数：[1-10之间的整数]
            资金管理：[风险控制建议，不超过80字]
            
            === 风险提示 ===
            [关键风险点和注意事项，不超过100字]
            
            【重要原则】
            - 必须基于提供的K线数据进行分析，不要编造数据
            - 价格建议要符合当前市场实际情况
            - 风险控制永远是第一优先级
            - 保持客观理性，避免过度乐观或悲观
            
            以下是 %s 的最近24小时K线数据：
            
            %s
            
            请严格按照上述格式输出你的专业分析结果。
            """, symbol, symbol, klineData);
    }
    
    /**
     * 调用AI API
     */
    private String callAiApi(String prompt) {
        try {
            String url = aiApiBaseUrl + "/chat/completions";
            
            // 构建请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.setBearerAuth(aiApiKey);
            
            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", aiModel);
            requestBody.put("messages", List.of(
                Map.of("role", "user", "content", prompt)
            ));
            requestBody.put("max_tokens", 2000);
            requestBody.put("temperature", 0.7);
            
            HttpEntity<Map<String, Object>> entity = new HttpEntity<>(requestBody, headers);
            
            log.info("调用AI API: {}", url);
            ResponseEntity<String> response = restTemplate.exchange(
                url, HttpMethod.POST, entity, String.class);
            
            if (response.getStatusCode() == HttpStatus.OK) {
                JsonNode jsonNode = objectMapper.readTree(response.getBody());
                String content = jsonNode.get("choices").get(0).get("message").get("content").asText();
                log.info("AI API调用成功，响应长度: {} 字符", content.length());
                return content;
            } else {
                throw new RuntimeException("AI API调用失败，状态码: " + response.getStatusCode());
            }
            
        } catch (Exception e) {
            log.error("AI API调用异常", e);
            throw new RuntimeException("AI API调用失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 解析AI响应，提取结构化数据
     */
    private TradingStrategyResponse parseAiResponse(String symbol, String aiResponse) {
        try {
            TradingStrategyResponse.TradingStrategyResponseBuilder builder = TradingStrategyResponse.builder();
            
            // 解析短期策略
            TradingStrategyResponse.ShortTermStrategy shortTerm = parseShortTermStrategy(aiResponse);
            builder.shortTermStrategy(shortTerm);
            
            // 解析长期策略
            TradingStrategyResponse.LongTermStrategy longTerm = parseLongTermStrategy(aiResponse);
            builder.longTermStrategy(longTerm);
            
            // 解析仓位管理
            TradingStrategyResponse.PositionManagement position = parsePositionManagement(aiResponse);
            builder.positionManagement(position);
            
            // 解析风险提示
            String riskWarning = extractSection(aiResponse, "=== 风险提示 ===", "");
            builder.riskWarning(riskWarning);
            
            return builder.build();
            
        } catch (Exception e) {
            log.error("解析AI响应失败", e);
            // 返回包含原始响应的策略对象
            return TradingStrategyResponse.builder()
                    .riskWarning("解析AI响应失败，请查看原始响应")
                    .build();
        }
    }
    
    /**
     * 解析短期策略
     */
    private TradingStrategyResponse.ShortTermStrategy parseShortTermStrategy(String response) {
        String section = extractSection(response, "=== 短期策略", "=== 长期策略");
        
        return TradingStrategyResponse.ShortTermStrategy.builder()
                .direction(extractValue(section, "方向："))
                .entryPrice(extractPrice(section, "进场价："))
                .takeProfitPrice(extractPrice(section, "止盈价："))
                .stopLossPrice(extractPrice(section, "止损价："))
                .reason(extractValue(section, "理由："))
                .timeFrame("1-4小时")
                .build();
    }
    
    /**
     * 解析长期策略
     */
    private TradingStrategyResponse.LongTermStrategy parseLongTermStrategy(String response) {
        String section = extractSection(response, "=== 长期策略", "=== 仓位管理");
        
        return TradingStrategyResponse.LongTermStrategy.builder()
                .direction(extractValue(section, "方向："))
                .entryPrice(extractPrice(section, "进场价："))
                .takeProfitPrice(extractPrice(section, "止盈价："))
                .stopLossPrice(extractPrice(section, "止损价："))
                .reason(extractValue(section, "理由："))
                .timeFrame("1-7天")
                .build();
    }
    
    /**
     * 解析仓位管理
     */
    private TradingStrategyResponse.PositionManagement parsePositionManagement(String response) {
        String section = extractSection(response, "=== 仓位管理", "=== 风险提示");
        
        return TradingStrategyResponse.PositionManagement.builder()
                .positionSizePercent(extractPercentage(section, "仓位比例："))
                .leverageMultiplier(extractInteger(section, "杠杆倍数："))
                .fundManagementAdvice(extractValue(section, "资金管理："))
                .build();
    }
    
    /**
     * 提取指定段落内容
     */
    private String extractSection(String text, String startMarker, String endMarker) {
        try {
            int startIndex = text.indexOf(startMarker);
            if (startIndex == -1) return "";
            
            int endIndex;
            if (endMarker.isEmpty()) {
                endIndex = text.length();
            } else {
                endIndex = text.indexOf(endMarker, startIndex + startMarker.length());
                if (endIndex == -1) endIndex = text.length();
            }
            
            return text.substring(startIndex + startMarker.length(), endIndex).trim();
        } catch (Exception e) {
            log.warn("提取段落失败: startMarker={}, endMarker={}", startMarker, endMarker);
            return "";
        }
    }
    
    /**
     * 提取字段值
     */
    private String extractValue(String text, String key) {
        try {
            Pattern pattern = Pattern.compile(key + "\\s*([^\\n]+)");
            Matcher matcher = pattern.matcher(text);
            if (matcher.find()) {
                return matcher.group(1).trim();
            }
        } catch (Exception e) {
            log.warn("提取值失败: key={}", key);
        }
        return null;
    }
    
    /**
     * 提取价格（处理各种格式）
     */
    private Double extractPrice(String text, String key) {
        try {
            String value = extractValue(text, key);
            if (value == null) return null;
            
            // 移除非数字字符，保留小数点
            String cleanValue = value.replaceAll("[^\\d.]", "");
            return Double.parseDouble(cleanValue);
        } catch (Exception e) {
            log.warn("提取价格失败: key={}", key);
            return null;
        }
    }
    
    /**
     * 提取百分比
     */
    private Double extractPercentage(String text, String key) {
        try {
            String value = extractValue(text, key);
            if (value == null) return null;
            
            String cleanValue = value.replaceAll("[^\\d.]", "");
            return Double.parseDouble(cleanValue);
        } catch (Exception e) {
            log.warn("提取百分比失败: key={}", key);
            return null;
        }
    }
    
    /**
     * 提取整数
     */
    private Integer extractInteger(String text, String key) {
        try {
            String value = extractValue(text, key);
            if (value == null) return null;
            
            String cleanValue = value.replaceAll("[^\\d]", "");
            return Integer.parseInt(cleanValue);
        } catch (Exception e) {
            log.warn("提取整数失败: key={}", key);
            return null;
        }
    }
    
    /**
     * 创建错误策略响应
     */
    private TradingStrategyResponse createErrorStrategy(String symbol, String errorMessage) {
        return TradingStrategyResponse.builder()
                .symbol(symbol)
                .generatedAt(LocalDateTime.now())
                .riskWarning("AI策略生成失败: " + errorMessage)
                .rawAiResponse("ERROR: " + errorMessage)
                .build();
    }
} 